﻿namespace Attacher
{
    using System;
    using System.Windows;
    using System.Windows.Threading;

    using Hardcodet.Wpf.TaskbarNotification;

    internal class UnhandledExceptionReportingService : IUnhandledExceptionReportingService
    {
        #region Attributes

        private readonly TaskbarIcon taskbarIcon;

        #endregion

        #region Constants

        private const string ErrorMessage = "Unexpected Exception Received" + "\n" + "The application will finish: {0}" + "\n" + "Message: {1}"; 

        #endregion

        #region Public Methods

        public UnhandledExceptionReportingService(TaskbarIcon taskbarIcon)
        {
            ParameterChecker.IsNotNull(taskbarIcon, "taskbarIcon");

            this.taskbarIcon = taskbarIcon;
        }

        public void Start()
        {
            Application.Current.DispatcherUnhandledException += this.CurrentOnDispatcherUnhandledException;   
            AppDomain.CurrentDomain.UnhandledException += this.CurrentDomainOnUnhandledException;
        }

        public void Stop()
        {
            Application.Current.DispatcherUnhandledException -= this.CurrentOnDispatcherUnhandledException;
            AppDomain.CurrentDomain.UnhandledException -= this.CurrentDomainOnUnhandledException;
        }

        #endregion

        #region Event Handlers

        private void CurrentOnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            this.NotifyException(e.Exception, false);
            
            e.Handled = true;
        }

        private void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            this.NotifyException((Exception)e.ExceptionObject, e.IsTerminating);
        }

        #endregion

        #region Private Methods

        private void NotifyException(Exception ex, bool isEnding)
        {
            this.taskbarIcon.ShowBalloonTip("Exception Detected", string.Format(ErrorMessage, isEnding, ex.Message), BalloonIcon.Error);
            
            if (isEnding)
            {
                // Show the message enough time to the user to see the message
                System.Threading.Thread.Sleep(3000);
            }
        }

        #endregion
    }
}
